﻿using AutoMapper;
using HikRcsService._631_Optical;
using HikRcsService.Common;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WCS_Entity.Dto.AutoEquipmentDto;
using WCS_Entity.Prorocol;
using WCS_Service.DomianService.Interface;
using WCS_Service.DomianService.Models;
using WCS_Service.Enums;
using WCS_Service.Interface;
using WCS_Service.Models.SerialNetModel;
using WCS_Service.ProtocolServices.Interface;
using WCS_Utility.ConstString;
using WCS_Utility.Extensions;

namespace WCS_Service.DomianService.AutoEquipmentDomain
{
    /// <summary>
    /// 光通信设备的领域服务
    /// </summary>
    public class OpticalDomainService : AutoEquipmentDomainService<OpticalCustomInfoModel>,IOpticalDomainService
    {
        public OpticalDomainService(IAutoEquipmentService autoEquipmentService, IComControl comControl, IMapper mapper) : base(autoEquipmentService, comControl, mapper)
        {
        }
        #region 属性
        public event Func<int, Task<SerialOpticalComModel>> OppsiteBuidChange;
        public event Func<string, Task> OppsiteDisConChange;
        #endregion

        #region public 
        /// <summary>
        /// 查询指定的光通信信息
        /// </summary>
        /// <returns></returns>
        public async Task<RunEqInfoModel<OpticalCustomInfoModel>> QueryOpticalInfoAsync(string id)
        {
            return await Task.Run(() =>  
            {
                if (!int.TryParse(id, out int key))
                {
                    return null;
                }
                if (!controlEquipments.TryGetValue(key, out RunEqInfoModel<OpticalCustomInfoModel> info))
                {
                    return null;
                }
                return info;
            });
        }
        /// <summary>
        /// 查询指定巷道的指定类型的光通信信息
        /// </summary>
        /// <param name="type"></param>
        /// <param name="roadwWay"></param>
        /// <returns></returns>
        public async Task<RunEqInfoModel<OpticalCustomInfoModel>> QueryAwqBaseRoadwayCodeAsync(OpticalType type, string roadwWay, string areaCode)
        {
            return await Task.Run(() => 
            {
                var groupInfo = controlEquipments?.GroupBy(c => c.Value.areaCode).Where(c => c.Key == areaCode)?.FirstOrDefault();
                if (groupInfo is null)
                {
                    Log.Error($"查询指定的光通信模块不存在!");
                    return null;
                }
                var info = groupInfo.FirstOrDefault(c => c.Value.customInfo.roadwayCode == roadwWay &&
                                          c.Value.customInfo.opticalType == type);
                return info.Value;
            });
            
        }
        /// <summary>
        /// 查询指定区域类型的可用光通信信息
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task<List<RunEqInfoModel<OpticalCustomInfoModel>>> QueryOpticalBaseTypeAsync(OpticalType type, string areaCode)
        {
            return await Task.Run(() => 
            {
                var groupInfo = controlEquipments?.GroupBy(c => c.Value.areaCode).Where(c => c.Key == areaCode)?.FirstOrDefault();
                if (groupInfo is null)
                {
                    Log.Error($"查询指定区域{areaCode}的类型{type.ToString()}的光通信模块不存在!");
                    return null;
                }
                var infos = groupInfo.Where(c => c.Value.customInfo.opticalType == type 
                                                       && c.Value.available)?.Select(c => c.Value).ToList();
                if (infos is null || !infos.Any())
                {
                    Log.Error($"查询指定区域{areaCode}的类型{type.ToString()}的光通信模块不存在!");
                    return null;
                }
                return infos;
            });
        }
        /// <summary>
        /// 查询指定类型的没有AGV停靠的光通讯信息
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task<RunEqInfoModel<OpticalCustomInfoModel>> QueryUnavailableOpticalBaseTypeAsync(OpticalType type, string areaCode)
        {
            return await Task.Run(() => 
            {
                var groupInfo = controlEquipments?.GroupBy(c => c.Value.areaCode).Where(c => c.Key == areaCode)?.FirstOrDefault();
                if (groupInfo is null)
                {
                    Log.Error($"查询指定的光通信模块不存在!");
                    return null;
                }
                return groupInfo.Where(c => c.Value.customInfo.opticalType == type 
                                                && !c.Value.available)?.Select(c => c.Value).FirstOrDefault();
            });
        }

        /// <summary>
        /// 查询充电点光通信信息
        /// </summary>
        /// <returns></returns>
        public async Task<RunEqInfoModel<OpticalCustomInfoModel>> QueryChargeOpticalAsync()
        {
            return await Task.Run(() =>
            {
                var info = controlEquipments?.Where(c => c.Value.customInfo.opticalType == OpticalType.Charge)?.Select(c => c.Value)?.FirstOrDefault();
                if (info is null)
                {
                    Log.Error($"查询指定类型充电点的光通信模块不存在!");
                    return null;
                }
                return info;
            });
        }
        /// <summary>
        /// 更新指定设备的锁定状态
        /// </summary>
        /// <param name="opticalId"></param>
        /// <param name="isLock"></param>
        /// <returns></returns>
        public async Task<bool> LockChargeOpticalChangeAsync(int opticalId,bool isLock)
        {
            return await Task.Run(() =>
            {
                if (!controlEquipments.TryGetValue(opticalId, out RunEqInfoModel<OpticalCustomInfoModel> info))
                {
                    return false;
                }
                if (info.isLock == isLock)
                {
                    return false;
                }
                info.isLock = isLock;
                controlEquipments.AddOrUpdate(opticalId,info, (key, value) => value);
                return true;
            });
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <returns></returns>
        public async Task SendMsgAsync(SerialOpticalComModel msg, int id)
        {
            if (msg is null)
            {
                Log.Error($"发送数据为空");
                return;
            }
            await SendInfoAsync(msg,id);
        }
        #endregion

        protected override async Task<OpticalCustomInfoModel> CustomEqInfoInitProcess(AutoEquipmentDto info)
        {
            OpticalCustomInfoModel opticalCustomInfoModel = new OpticalCustomInfoModel();
            opticalCustomInfoModel.opticalType = info.Extend1.StringToEnum<OpticalType>();
            opticalCustomInfoModel.roadwayCode = info.Extend2;
            return opticalCustomInfoModel;
        }

        /// <summary>
        /// 连接中的自动化设备信息管理
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="type"></param>
        protected override void RunEquipmentUpdate(int id, ConEquipmentState state, string type)
        {
            if (type != ConstStringData.Optical_eq)
            {
                return;
            }
            base.RunEquipmentUpdate(id, state, type);
        }
        /// <summary>
        /// 协议服务初期处理
        /// </summary>
        /// <param name="service"></param>
        /// <returns></returns>
        protected override async Task ProtocolServiceInitAsync(IProtocolService service, List<ProtocolEntity> protocolParas,Func<string, Task<Func<string,int, Task>?>> execute)
        {
            if (service.isSerialNet && execute is not null)
            {
                var msgPara = protocolParas.FirstOrDefault();
                var methond = await execute(msgPara.messageType);
                if (methond is null)
                {
                    Log.Error($"透传协议接收处理方法获取失败!");
                    return;
                }
                service.ReceiveMsgBusinessEvent += methond;
            }
            //绑定光通信对端建立通信后处理
            service.OppositeConChange += OppositeComConAsync;
        }
        #region private 
        /// <summary>
        /// 光通信对端通信建立的场合
        /// </summary>
        /// <param name="eqNumber"></param>
        private async Task OppositeComConAsync(int eqNumber, ConEquipmentState state)
        {
            switch (state)
            {
                case ConEquipmentState.Connect:
                    await OppsiteConBuidAsync(eqNumber);
                    break;
                case ConEquipmentState.DisConnect:
                    await OppsiteConDisAsync(eqNumber);
                    break;
            }
        }
        /// <summary>
        /// 对端通信建立
        /// </summary>
        /// <returns></returns>
        private async Task OppsiteConBuidAsync(int id)
        {
            //更新状态
            await UpdateEquipmentAvailableAsync(id, true);
            if (OppsiteBuidChange is not null)
            {
                var msg = await OppsiteBuidChange?.Invoke(id);
                if (msg is null) return;
                await SendInfoAsync(msg, id);
            }
        }
        /// <summary>
        /// 对端通信断开
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private async Task OppsiteConDisAsync(int id)
        {
            //更新状态
            await UpdateEquipmentAvailableAsync(id, false);
            OppsiteDisConChange?.Invoke(id.ToString());
        }

        private async Task SendInfoAsync(SerialOpticalComModel msg,int id)
        {
            var service = await QueryComServiceBaseId(id);

            if (service is null && service.protocolService is null)
            {
                Log.Error($"指定{id}光通信模块不存在!");
                return;
            }
            if (msg is null)
            {
                return;
            }
            //拼接光通信协议报文
            var sendMsg = await service.protocolService.SetSerialNetDataAsync(msg);
            
            //添加消息结尾标识
            var info = await service.protocolService.SendMsgSplicingAsync(sendMsg);
            if (info is null) return;

            await service.SendAsync(info);
        }
        #endregion
    }
}
